/*
XML:
<?xml version="1.0" encoding="ISO-8859-1"?>
<FILE id="1" major_version="1" minor_version="1">
<ChunkBlock name="mesh" count="3">
<ChunkBlock name="map" count="2">
123.bmp
./resource/123.bmp
</ChunkBlock>
<ChunkBlock name="vertices3d" number="3">
1.0 2.0 3.0
</ChunkBlock>
<ChunkBlock name="index" number="3">
1 2 3
</ChunkBlock>
</ChunkBlock>
</FILE>

DATA:
number of subchunk 1
--chunk size 
--chunk id mesh(DWORD)
--chunk data 
----number of chunk 3
------chunk size
------chunk id map(DWORD) 
------chunk data
------chunk size
------chunk id vertices3d(DWORD)
------chunk data
------chunk size
------chunk id index(DWORD)
------chunk data
*/
#define XML_CONVERT
#include "stdafx.h"
#include "tinyxml.h"
#include "tinystr.h"

boost::shared_ptr<TiXmlDocument> g_doc;
boost::shared_ptr<DataStream> g_ds;

string& operator>> (string& strSrc, string& strDes)
{
	size_t length=strSrc.length();
	size_t ofsBegin=strSrc.find_first_not_of(" \t\r\n");
	if(ofsBegin==string::npos)
		return strSrc;
	size_t ofsEnd=strSrc.find_first_of(" \t\r\n",ofsBegin+1);
	if(ofsEnd==string::npos)
		ofsEnd=length;
	strDes=strSrc.substr(ofsBegin,ofsEnd-ofsBegin);
	if((length-ofsEnd)<=0)
		strSrc="";
	else
		strSrc=strSrc.substr(ofsEnd+1,length-ofsEnd);
	return strSrc;

}

bool LoadString(pair<char*,size_t>& data, string& text)
{
	cout<<"LoadString"<<text<<endl;
	Vector<string> tmpData;
	size_t length=0;
	while(true)
	{
		string tmp;
		text>>tmp;
		if(tmp=="")
			break;
		tmpData.push_back(tmp);
		length+=tmp.length()+1;
	}
	data.second=length;
	data.first=new char[length];
	char* p=data.first;
	for(Vector<string>::iterator iter=tmpData.begin();iter!=tmpData.end();iter++)
	{
		strcpy_s(p,iter->length()+1,iter->c_str());
		p+=iter->length()+1;
	}
	return true;
}

bool LoadInt(pair<char*,size_t>& data, string& text)
{
	cout<<"LoadInt"<<text<<endl;
	try
	{
		Vector<int> tmpData;
		while(true)
		{
			string tmp;
			text>>tmp;
			if(tmp=="")
			{
				break;
			}
			int i=boost::lexical_cast<int>(tmp);
			tmpData.push_back(i);
		}
		data.second=sizeof(int)*tmpData.size();
		data.first=new char[data.second];
		char* p=data.first;
		for(Vector<int>::iterator iter=tmpData.begin();iter!=tmpData.end();iter++)
		{
			memcpy_s(p,sizeof(int),(void*)(&(*iter)),sizeof(int));
			p+=sizeof(int);
		}
	}
	catch( ... )
	{
		cout<<"error"<<endl;
	}
	return true;
}

bool LoadFloat(pair<char*,size_t>& data, string& text)
{
	cout<<"LoadFloat"<<text<<endl;
	Vector<float> tmpData;
	while(true)
	{
		string tmp;
		text>>tmp;
		if(tmp=="")
		{
			break;
		}
		float f=boost::lexical_cast<float>(tmp);
		tmpData.push_back(f);
	}
	data.second=sizeof(float)*tmpData.size();
	data.first=new char[data.second];
	char* p=data.first;
	for(Vector<float>::iterator iter=tmpData.begin();iter!=tmpData.end();iter++)
	{
		memcpy_s(p,sizeof(float),(void*)(&(*iter)),sizeof(float));
		p+=sizeof(float);
	}
	return true;
}

pair<char*,size_t> LoadData(const string* name, string& data,int number)
{
	cout<<"LoadData"<<*name<<endl;
	pair<char*,size_t> rt;
	if(*name=="string")
	{
		LoadString(rt,data);
	}
	else if(*name=="int")
	{
		LoadInt(rt,data);
	}
	else if(*name=="float")
	{
		LoadFloat(rt,data);
	}
	else
	{
		EXCEPTION(*name);
	}
	return rt;
}

Vector<Chunk*> LoadSubElement(TiXmlElement* e)
{
	cout<<"LoadSubElement"<<endl;
	Vector<Chunk*> rt;
	for(e;e;e=e->NextSiblingElement())
	{
		Chunk* tmp;
		const string* nameAttr=e->Attribute(string("name"));
		const string nameElement=e->ValueStr();
		if(nameAttr==NULL)
			EXCEPTION("Name attribute not found in sub chunk")
		TiXmlElement* sube=e->FirstChildElement();
		if(sube==NULL)
		{
			const string* numberAttr=e->Attribute(string("number"));
			int n=0;
			if(numberAttr!=NULL)
			{
				n=boost::lexical_cast<int>(*numberAttr);
			}
			const char* tmpText=e->GetText();
			if(tmpText==NULL)
				EXCEPTION("Data not found in sub chunk")
				string data(tmpText);
			pair<char*,size_t> pc=LoadData(&nameElement,data,n);
			tmp=new Chunk(*nameAttr,pc.second,pc.first);
		}
		else
		{
			Vector<Chunk*> subChunk=LoadSubElement(e->FirstChildElement());
			tmp=new Chunk(*nameAttr,subChunk);
		}
		rt.push_back(tmp);
	}
	return rt;
}

bool ConvertToData(string filename)
{
	try
	{
	size_t pos=0;
	pos= filename.find_last_of(".");
	string storeFileName;
	storeFileName=filename.substr(0,pos+1);
	storeFileName+="data";
	pos=storeFileName.find_last_of("/")+1;
	string m_name=storeFileName.substr(pos,storeFileName.length()-pos);
	TiXmlElement* tmpHeaderElement = g_doc->RootElement();
	const string* name=tmpHeaderElement->Attribute(string("name"));
	if(name==NULL)
		EXCEPTION("Name attribute not found in File Element")
	const string* cmajor=tmpHeaderElement->Attribute(string("major_version"));
	if(cmajor==NULL)
		EXCEPTION("Major attribute not found in File Element")
		const string* cminor=tmpHeaderElement->Attribute(string("minor_version"));
	if(cminor==NULL)
		EXCEPTION("Minor attribute not found in File element")
	unsigned int major=boost::lexical_cast<unsigned int>(*cmajor);
	unsigned int minor=boost::lexical_cast<unsigned int>(*cminor);

	/*
	start to push chunk in datastream
	*/
	tmpHeaderElement=tmpHeaderElement->FirstChildElement();
	if(tmpHeaderElement==NULL)
		return false;
	Chunk* mainChunk;
	Vector<Chunk*> subChunk;
	const string* nameAttr=tmpHeaderElement->Attribute(string("name"));
	const string nameElement=tmpHeaderElement->ValueStr();
	if(nameAttr==NULL)
		EXCEPTION("Mame attribute not found in main chunk")

	TiXmlElement* sube=tmpHeaderElement->FirstChildElement();
	if(sube==NULL)
	{
		const string* numberAttr=tmpHeaderElement->Attribute(string("number"));
		int n=0;
		if(numberAttr!=NULL)
		{
			n=boost::lexical_cast<int>(*numberAttr);
		}
		const char* tmpText=tmpHeaderElement->GetText();
		if(tmpText==NULL)
			EXCEPTION("Data not found in main chunk")
		string data(tmpText);
		pair<char*,size_t> pc=LoadData(&nameElement,data,n);
		mainChunk=new Chunk(*nameAttr,pc.second,pc.first);
	}
	else
	{
		Vector<Chunk*> subChunk=LoadSubElement(tmpHeaderElement->FirstChildElement());
		mainChunk=new Chunk(*nameAttr,subChunk);

	}
	
		g_ds=boost::make_shared<DataStream>(storeFileName,m_name,major<<16|minor,mainChunk);
		g_ds->Save();
	}
	catch(std::exception& e)
	{
		PRINT_ERROR(e)
	}
	return true;
}

int main(int argc, char* argv[])
{
	//DataStream ds("temp.txt",DataStream::READ_ONLY);
	if(argc!=2)
	{
		cout<<"Command line error!"<<endl;
		return -1;
	}
	g_doc=boost::make_shared<TiXmlDocument>( argv[1] );
	bool loadOkay = g_doc->LoadFile();

	if (loadOkay)
	{
		bool result=ConvertToData(argv[1]);
		if(!result)
		{
			cout<<"Could not convert this file"<<endl;
		}
	}
	else
	{
		cout<<"Failed to load file "<<argv[1]<<endl;
	}
	return 0;
}
